%include	"pm.inc"
        
[SECTION .s16]
[BITS	16]     
       	mov	ax,     cs
	mov	ds,     ax          
	mov	es,     ax         
   
        mov     ax,     8000h
	mov	ss,     ax          
	mov	sp,     0000h       
 
        call    clear_screen
        call    load_kernel
        call    load_kernel
        call    kill_motor
        call    move_kernel
        
	xor	eax, eax
	mov	ax, ds
	shl	eax, 4
	add	eax, gdt
	mov	dword [gdtr + 2], eax	

	lgdt	[gdtr]

	cli

	in	al, 92h
	or	al, 00000010b
	out	92h, al

	mov	eax, cr0
	or	eax, 1
	mov	cr0, eax

	jmp	dword SELECTOR_CODE:(SETUP_SEG*10h+TEST)
        
        
load_kernel:
.lk_rest:
        mov     ax,     KERNEL_TMP_SEG
        mov     es,     ax

        mov     bx,     KERNEL_OFFSET
	xor	dx,     dx
        
	mov	ch,     00h   		                                      
        mov     cl,     06h                                     ; No.6 Sector --- Kernel
	mov	ah,     2             	                        
        mov     al,     13                                      ; 13 sectors (from 6 to 18) 
	int	13h		                        	
	jnc     .lk_next_track	                                
        xor	dl,     dl                                      
	xor	ah,     ah                                     
	int	13h
	jmp	.lk_rest
.lk_next_track:
        cmp     byte [track_no],  1Ah
        jz      .lk_end
        add     byte [track_no],  01h
        call    load_track
        jmp     .lk_next_track    
.lk_end:
        ret

        
load_track:
        mov     ax,     KERNEL_TMP_SEG                                  
        mov     es,     ax
	xor	dx,     dx		                        
	mov	ch,     byte [track_no]		                          
        mov     cl,     01h
        xor     bx,     bx
        mov     bl,     ch
        dec     bl
        mov     ax,     512
        mul     bx
        add     bx,     KERNEL_OFFSET                           
        add     bx,     6656                                    
	mov	ah,     2             	                        
        mov     al,     18                                      
	int	13h		                        	
	jnc     .ld_end		                                
        xor	dl,     dl                                       
	xor	ah,     ah
	int	13h
	jmp	load_track
.ld_end:
        ret

                
        
clear_screen:
	mov	ax, 0600h	                	
	mov	bx, 0700h	                
	mov	cx, 0		                	
	mov	dx, 0184Fh	                
	int	10h		                
        ret



disp_msg:
	mov	ax,     msg
	mov	bp,     ax			
	mov	ax,     ds			
	mov	es,     ax	                         
	mov	cx,     10                              
	mov	ax,     1301h	                    	 
	mov	bx,     0009h	                	 
        mov     dh,     byte [msgy]
	mov	dl,     0                               
        add     byte [msgy], 1
	int	10h
        ret

        
kill_motor:
	mov	dx,     03F2h
	mov	al,     0
	out	dx,     al
	ret

        
move_kernel:
        push    ds
        mov     ax,     KERNEL_TMP_SEG
        mov     ds,     ax        
        mov     ax,     KERNEL_NEW_SEG
        mov     es,     ax
        mov     cx,     8000h
        mov     ax,     8                                ; 8000h * 8 B = 256 KB
        xor     di,     di
        xor     si,     si
        cld                                              ; ds:si --> es:di
.mk_loop:
        cmp     ax,     0
        jz      .mk_end
        dec     ax
        rep
        movsb
        jmp     .mk_loop
.mk_end:
        pop     ds
        ret
        
track_no:
        db      0

msg:
        db      "Loading..."

msgy:
        db      0

        

[SECTION .gdt]        

gdt:
      Descriptor         0,      0,  0
desc_pg_dir:
      Descriptor PageDirBase, 4095,  DA_DRW                     
desc_pg_table:
      Descriptor PageTblBase, 1023,  DA_DRW  |DA_LIMIT_4K         
desc_code:
      Descriptor         0, 0fffffh, DA_CR  | DA_32 | DA_LIMIT_4K 
desc_data:
      Descriptor         0, 0fffffh, DA_DRW | DA_32 | DA_LIMIT_4K                     
desc_video:
      Descriptor   0B8000h,  0ffffh, DA_DRW	     
        
GDT_LEN		equ	$ - gdt	
gdtr		dw	GDT_LEN - 1	
		dd	0		

SELECTOR_CODE		equ	desc_code       -  gdt
SELECTOR_DATA           equ     desc_data       -  gdt        
SELECTOR_VIDEO		equ	desc_video      -  gdt 
SELECTOR_PG_DIR		equ	desc_pg_dir	-  gdt
SELECTOR_PG_TABLE	equ	desc_pg_table	-  gdt

PageDirBase		equ	200000h	; 页目录开始地址: 2M
PageTblBase		equ	201000h	; 页表开始地址: 2M+4K
        
KERNEL_TMP_SEG          equ             0050h
KERNEL_NEW_SEG          equ             0000h
KERNEL_OFFSET           equ             0000h
SETUP_SEG               equ             9F30h           ; See also boot/boot.s 
KERNEL_PHYSICAL_ADDR    equ             KERNEL_NEW_SEG*10+KERNEL_OFFSET        
KERNEL_ENTRY_POINT      equ             0500h
        
[SECTION .s32]
[BITS	32]

TEST:
        call    setup_paging
        mov     ax,     SELECTOR_VIDEO
        mov     gs,     ax
        mov     ax,     SELECTOR_DATA
        mov	ds,     ax
	mov	es,     ax
	mov	fs,     ax
	mov	ss,     ax      
        
	jmp	SELECTOR_CODE:(KERNEL_PHYSICAL_ADDR + KERNEL_ENTRY_POINT)
        

setup_paging:
       	mov	ax,     SELECTOR_PG_DIR
	mov	es,     ax
	mov	ecx,    1024	
	xor	edi,    edi
	xor	eax,    eax
	mov	eax,    PageTblBase | PG_P  | PG_USU | PG_RWW
.1:
	stosd
	add	eax,    4096	
	loop	.1
	mov	ax,     SELECTOR_PG_TABLE	
	mov	es,     ax
	mov	ecx,    1024 * 1024	
	xor	edi,    edi
	xor	eax,    eax
	mov	eax,    PG_P  | PG_USU | PG_RWW
.2:
	stosd
	add	eax,    4096		
	loop	.2
	mov	eax,    PageDirBase
	mov	cr3,    eax
	mov	eax,    cr0
	or	eax,    80000000h
	mov	cr0,    eax
	jmp	short .3
.3:
	nop
	ret

        